
#include <vcl.h>
#pragma hdrstop
#include <float.h>
#include <math.h>
#include <stdlib.h>
#include <db.hpp>
#include <eic.h>
#include "fonction.hpp"
#include "uFormules.h"
#define MODULE_TAG MODULE_TAG_FORMULE

//Explications : (grammaire)
// <Programme>                  = <Groupe instructions>
// <Groupe instructions>        = NULL | <Instruction><Groupe instructions> |{<Groupe instructions>}
// <Groupe instructions simple> = <Instruction> |{<Groupe instructions>}
// <Instruction>                = ';' | <Mot clé C> | <Groupe element>';'
// <Groupe element>             = NULL|<Element><Groupe element>|(<Groupe element>)
// <Groupe element simple>      = <Element>|(<Element><Groupe element>)
// <Element>                    = <Variable> | <Fonction> | <Nombre> | <Chaine>
// <Fonction>                   = <Fonction num> | <Fonction chaine>
// <Nombre>                     = ?.?
// <Chaine>                     = "???"

typedef AnsiString __fastcall (__closure *VAR_FUNC)(bool bAFaire);
typedef bool       __fastcall (__closure *VAR_INSTR)(bool bAFaire);

const cHelp TVar::TabHelp[] =
{
    {"==",                   "<expression1> == <expression2>"},
    {"!=",                   "<expression1> != <expression2>"},
    {"=",                    "<Variable> = <expression>"},
    {">=",                   "<expression1> >= <expression2>"},
    {"<=",                   "<expression1> <= <expression2>"},
    {">",                    "<expression1> > <expression2>"},
    {"<",                    "<expression1> < <expression2>"},
    {"IsNull",               "IsNull( Variable chaine ou numérique)"},
};
const cHelp TVarNum::TabHelp[] =
{
    {"&&",                   "<expression num> && <expression num>"},
    {"||",                   "<expression num> || <expression num>"},
    {"+=",                   "<variable num> += <expression num>"},
    {"+",                    "<expression1 num> + <expression2 num>"},
    {"-",                    "<expression1 num> - <expression2 num>"},
    {"*",                    "<expression1 num> * <expression2 num>"},
    {"/",                    "<expression1 num> / <expression2 num>"},
    {"abs",                  "abs( num n)"},
    {"length",               "length( string chaine)"},
    {"div",                  "div( num numer, num denom)"},
    {"round",                "round( num nombre, num precision)"},
    {"mod",                  "mod( num numer, num denom)"},
    {"pos",                  "pos( string chaine, string souschaine)"},
    {"min",                  "min( num nombre1, num nombre2)"},
    {"max",                  "max( num nombre1, num nombre2)"},
    {"StringToNum",          "StringToNum( string chaine)"},
    {"Sqrt",                 "Sqrt( num nombre)"},
    {"pow",                  "pow( num nombre)"},
    {"pourcent",             "pourcent( num nombre, num pourcentage)"},
    {"DecodeDate",           "DecodeDate(string chaine, num year, num month, num day)"},
    {"DecodeTime",           "DecodeTime(string chaine, num hour, num min, num sec)"},
    {"CurrentDay",           "CurrentDay()"},
    {"CurrentMonth",         "CurrentMonth()"},
    {"CurrentYear",          "CurrentYear()"},
    {"CurrentHour",          "CurrentHour()"},
    {"CurrentMin",           "CurrentMin()"},
    {"CurrentSec",           "CurrentSec()"},
};
const cHelp TVarChaine::TabHelp[] =
{
    {"+",                    "<Variable string> += <expression string>"},
    {"+=",                   "<expression string> += <expression string>"},
    {"LowerCase",            "LowerCase( string s)"},
    {"UpperCase",            "UpperCase( string s)"},
    {"NumToString",          "NumToString( num x)"},
    {"CurrentDateToStr",     "CurrentDateToStr( )"},
    {"CurrentTimeToStr",     "CurrentTimeToStr( )"},
    {"CurrentDateTimeToStr", "CurrentDateTimeToStr( )"},
    {"SubString",            "SubString( string s, num index, num count)"},
};
const cHelp TCalculDeFormules::TabHelp[] =
{
    {"return",               "return [ <expression>] ;"},
    {"if",                   "if( <condition>)  <instruction1>;\nelse  <instruction2>;"},
    {"else",                 "if( <condition>)  <instruction1>;\nelse  <instruction2>;"},
    {"for",                  "for ( [<initialisation>]; [<condition>]; [<incrément>] )  <instruction>"},
    {"do",                   "do <instruction> while( <condition> },"},
    {"while",                "while( <condition>) <instruction>"},
    {"num",                  "Déclaration de variable numérique"},
    {"string",               "Déclaration de variable alphanumérique"},
};
//---------------------------------------------------------------------------
void __fastcall TVar::Lit2Params( AnsiString &a, AnsiString &b, bool bAFaire)
{
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ","));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( b, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
}
//---------------------------------------------------------------------------
void __fastcall TVar :: Help( TTreeNode *t)
{
  m_Calc->Help(t,TabHelp,ARRAYSIZE(TabHelp));
}
/*void  __fastcall  TVar :: Help( TTreeNode *tNode)
{
    m_Calc->AddHelp( tNode, "==", "<expression1> == <expression2>");
    m_Calc->AddHelp( tNode, "!=", "<expression1> != <expression2>");
    m_Calc->AddHelp( tNode, "=",  "<Variable> = <expression>");
    m_Calc->AddHelp( tNode, ">=", "<expression1> >= <expression2>");
    m_Calc->AddHelp( tNode, "<=", "<expression1> <= <expression2>");
    m_Calc->AddHelp( tNode, ">",  "<expression1> > <expression2>");
    m_Calc->AddHelp( tNode, "<",  "<expression1> < <expression2>");
    m_Calc->AddHelp( tNode, "IsNull",  "IsNull( Variable chaine ou numérique)");
}*/
//---------------------------------------------------------------------------
AnsiString __fastcall TVar::operator=( bool bAFaire)
{
    m_Valeur = (m_Type == ftFloat) ? "0": "";
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( m_Valeur, bAFaire, this));
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVar::operator==( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    return a == Valeur? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVar::operator!=( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    return a != Valeur? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVar::IsNull( bool bAFaire)
{
    return Valeur.IsEmpty()? "1" : "0";
}
//---------------------------------------------------------------------------
void __fastcall TVarNum :: Help( TTreeNode *t)
{
  m_Calc->Help(t,TabHelp,ARRAYSIZE(TabHelp));
}
/*void  __fastcall  TVarNum:: Help( TTreeNode *tNode)
{
    m_Calc->AddHelp( tNode, "&&",           "<expression num> && <expression num>");
    m_Calc->AddHelp( tNode, "||",           "<expression num> || <expression num>");
    m_Calc->AddHelp( tNode, "+=",           "<variable num> += <expression num>");
    m_Calc->AddHelp( tNode, "+",            "<expression1 num> + <expression2 num>");
    m_Calc->AddHelp( tNode, "-",            "<expression1 num> - <expression2 num>");
    m_Calc->AddHelp( tNode, "*",            "<expression1 num> * <expression2 num>");
    m_Calc->AddHelp( tNode, "/",            "<expression1 num> / <expression2 num>");
    m_Calc->AddHelp( tNode, "abs",          "abs( num n)");
    m_Calc->AddHelp( tNode, "length",       "length( string chaine)");
    m_Calc->AddHelp( tNode, "div",          "div( num numer, num denom)");
    m_Calc->AddHelp( tNode, "round",        "round( num nombre, num precision)");
    m_Calc->AddHelp( tNode, "mod",          "mod( num numer, num denom)");
    m_Calc->AddHelp( tNode, "pos",          "pos( string chaine, string souschaine)");
    m_Calc->AddHelp( tNode, "min",          "min( num nombre1, num nombre2)");
    m_Calc->AddHelp( tNode, "max",          "max( num nombre1, num nombre2)");
    m_Calc->AddHelp( tNode, "StringToNum",  "StringToNum( string chaine)");
    m_Calc->AddHelp( tNode, "Sqrt",         "Sqrt( num nombre)");
    m_Calc->AddHelp( tNode, "pow",          "pow( num nombre)");
    m_Calc->AddHelp( tNode, "pourcent",     "pourcent( num nombre, num pourcentage)");
    m_Calc->AddHelp( tNode, "DecodeDate",   "DecodeDate(string chaine, num year, num month, num day)");
    m_Calc->AddHelp( tNode, "DecodeTime",   "DecodeTime(string chaine, num hour, num min, num sec)");
    m_Calc->AddHelp( tNode, "CurrentDay",   "CurrentDay()");
    m_Calc->AddHelp( tNode, "CurrentMonth", "CurrentMonth()");
    m_Calc->AddHelp( tNode, "CurrentYear",  "CurrentYear()");
    m_Calc->AddHelp( tNode, "CurrentHour",  "CurrentHour()");
    m_Calc->AddHelp( tNode, "CurrentMin",   "CurrentMin()");
    m_Calc->AddHelp( tNode, "CurrentSec",   "CurrentSec()");
}*/
//---------------------------------------------------------------------------
void __fastcall TVarNum::SetValeur( const AnsiString &s)
{
TRACEF( TAGL, "SetValeur Deb [%s]", s.c_str());
    AnsiString s2 = s;
    for( int i = 1; i <= s2.Length(); i++)
    {
        if( s2[i] == '.')
            s2[i] = DecimalSeparator;
    }
    if( IsValeurSignificative(s2)) m_Valeur = s2.ToDouble();
    else                           m_Valeur = Glob->asD_NS;
TRACEF( TAGL, "SetValeur Fin [%s]", s.c_str());
}
//---------------------------------------------------------------------------
double __fastcall TVarNum::ToDoubleDNS( const AnsiString &s)
{
    try{
        if( !IsValeurSignificative(s))
            return 0;
        return s.ToDouble();
    }catch(...)
    {
        return 0;
    }
}
//---------------------------------------------------------------------------
bool __fastcall TVarNum::IsDNS( const AnsiString &s)
{
    return !IsValeurSignificative(s);
}

//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator>=( bool bAFaire)
{
    AnsiString a;
    TVarNum *v = new TVarNum( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
//    a = v->Valeur;
    delete v;
    return ToDoubleDNS(Valeur) >= ToDoubleDNS(a)? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator<=( bool bAFaire)
{
    AnsiString a;
    TVarNum *v = new TVarNum( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
//    a = v->Valeur;
    delete v;
    return ToDoubleDNS(Valeur) <= ToDoubleDNS(a)? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator>( bool bAFaire)
{
    AnsiString a;
    TVarNum *v = new TVarNum( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
//    a = v->Valeur;
    delete v;
    return ToDoubleDNS(Valeur) > ToDoubleDNS(a)? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator<( bool bAFaire)
{
    AnsiString a;
    TVarNum *v = new TVarNum( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
//    a = v->Valeur;
    delete v;
    return ToDoubleDNS(Valeur) < ToDoubleDNS(a)? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator&&( bool bAFaire)
{
    AnsiString a;
    TVarNum *v = new TVarNum( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
//    a = v->Valeur;
    delete v;
    return ToDoubleDNS(Valeur) && ToDoubleDNS(a)? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator||( bool bAFaire)
{
    AnsiString a;
    TVarNum *v = new TVarNum( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
//    a = v->Valeur;
    delete v;
    return ToDoubleDNS(Valeur) || ToDoubleDNS(a)? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator+=( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    if( !IsDNS(Valeur) || !IsDNS(a))
    {
        Valeur = ToDoubleDNS(Valeur) + ToDoubleDNS(a);
    }
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator+( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL, EL_Simple));
    if( IsDNS(Valeur) && IsDNS(a))      return Valeur;
    return AnsiString( ToDoubleDNS(Valeur) + ToDoubleDNS(a));
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator-( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL, EL_Simple));
    if( IsDNS(Valeur) && IsDNS(a))      return Valeur;
    return AnsiString( ToDoubleDNS(Valeur) - ToDoubleDNS(a));
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator*( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL, EL_Simple));
    if( IsDNS(Valeur) && IsDNS(a))      return Valeur;
    return AnsiString( ToDoubleDNS(Valeur) * ToDoubleDNS(a));
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::operator/( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL, EL_Simple));
    if( IsDNS(Valeur) && IsDNS(a)  )    return Valeur;
    if( !ToDoubleDNS(a))                return "ERREUR Division par zéro";
    return AnsiString( ToDoubleDNS(Valeur) / ToDoubleDNS(a));
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::abs( bool bAFaire)
{
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( Valeur, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    if( IsDNS(Valeur))     return Valeur;
    return fabs( Valeur.ToDouble() );
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::length( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    return AnsiString(ToDoubleDNS(a)).Length();
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::div( bool bAFaire)
{
    AnsiString a, b;
    div_t nValeurLoc;
    Lit2Params( a, b, bAFaire);
    if( IsDNS(a) && IsDNS(b) )          return a;
    if( !ToDoubleDNS(b))                return "ERREUR Division par zéro";
    nValeurLoc =  ::div( ToDoubleDNS(a), ToDoubleDNS(b));
    Valeur = nValeurLoc.quot;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::round( bool bAFaire)
{
    AnsiString a, b;
    Lit2Params( a, b, bAFaire);
    if( IsDNS(a) || IsDNS(b))           return a;
    Valeur = Round( ToDoubleDNS(a), int(ToDoubleDNS(b)) );
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::mod( bool bAFaire)
{
    AnsiString a, b;
    div_t nValeurLoc;
    Lit2Params( a, b, bAFaire);
    if( IsDNS(a) && IsDNS(b) )          return a;
    if( !ToDoubleDNS(b))                return "ERREUR Division par zéro";
    nValeurLoc =  ::div( ToDoubleDNS(a), ToDoubleDNS(b));
    Valeur = ToDoubleDNS(a) - nValeurLoc.quot * ToDoubleDNS(b);
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::pos( bool bAFaire)
{
    AnsiString a, b;
    Lit2Params( a, b, bAFaire);
    Valeur = a.Pos( b);
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::min( bool bAFaire)
{
    AnsiString a, b;
    Lit2Params( a, b, bAFaire);
    Valeur = ::min( ToDoubleDNS( a), ToDoubleDNS( b));
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::max( bool bAFaire)
{
    AnsiString a, b;
    Lit2Params( a, b, bAFaire);
    Valeur = ::max( ToDoubleDNS( a), ToDoubleDNS( b));
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::StringToNum( bool bAFaire)
{
    AnsiString a;
    TVarChaine *v = new TVarChaine( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    delete v;
    try{
        Valeur = ToDoubleDNS( a);
    }catch(...)
    { Valeur = D_NS; a = Glob->asD_NS; }
    return a;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::Sqrt( bool bAFaire)
{
    AnsiString a, b;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( Valeur, bAFaire, this));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    if( IsDNS( Valeur)) return Valeur;
    Valeur = sqrt(a.ToDouble( ));
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::pow( bool bAFaire)
{
    AnsiString a, b;
    Lit2Params( a, b, bAFaire);
    if( IsDNS( a) || IsDNS( b)) return Glob->asD_NS;
    Valeur = ::pow( a.ToDouble(), b.ToDouble());
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::pourcent( bool bAFaire)
{
    AnsiString a, b;
    Lit2Params( a, b, bAFaire);
    if( IsDNS( a) || IsDNS( b)) return Glob->asD_NS;
    Valeur = (a.ToDouble()/100)*b.ToDouble();
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::DecodeDate( bool bAFaire)
{
    unsigned short year, month, day;
    AnsiString aYear, aMonth, aDay;
    TVarNum *vYear, *vMonth, *vDay;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( Valeur, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ","));
    m_Calc->throwIfFalse( m_Calc->LitNomVariable( aYear), "DecodeDate param year");
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ","));
    m_Calc->throwIfFalse( m_Calc->LitNomVariable( aMonth), "DecodeDate param Month");
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ","));
    m_Calc->throwIfFalse( m_Calc->LitNomVariable( aDay), "DecodeDate param Day");
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    vYear = dynamic_cast<TVarNum*>(m_Calc->GetVariable( aYear));
    vMonth = dynamic_cast<TVarNum*>(m_Calc->GetVariable( aMonth));
    vDay = dynamic_cast<TVarNum*>(m_Calc->GetVariable( aDay));
    try{
        TDateTime(Valeur).DecodeDate( &year, &month, &day);
        vYear->Valeur = year;         vMonth->Valeur = month;         vDay->Valeur = day;
    }catch(EConvertError &e)
    {
        m_Calc->throwIfFalse( false, "Premier paramètre de DecodeDate incorrect : '" + Valeur + "' n'est pas un temps correct");
    }
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::DecodeTime( bool bAFaire)
{
    unsigned short hour, min, sec, dsec;
    AnsiString aHour, aMin, aSec;
    TVarNum *vHour, *vMin, *vSec;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( Valeur, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ","));
    m_Calc->throwIfFalse( m_Calc->LitNomVariable( aHour), "DecodeTime param Hour");
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ","));
    m_Calc->throwIfFalse( m_Calc->LitNomVariable( aMin), "DecodeTime param Min");
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ","));
    m_Calc->throwIfFalse( m_Calc->LitNomVariable( aSec), "DecodeTime param Sec");
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    vHour = dynamic_cast<TVarNum*>(m_Calc->GetVariable( aHour));
    vMin = dynamic_cast<TVarNum*>(m_Calc->GetVariable( aMin));
    vSec = dynamic_cast<TVarNum*>(m_Calc->GetVariable( aSec));
    try{
        TDateTime(Valeur).DecodeTime( &hour, &min, &sec, &dsec);
        vHour->Valeur = hour;         vMin->Valeur = min;         vSec->Valeur = sec;
    }catch(EConvertError &e)
    {
        m_Calc->throwIfFalse( false, "Premier paramètre de DecodeDate incorrect : '" + Valeur + "' n'est pas un temps correct");
    }
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::CurrentDay( bool bAFaire)
{
    unsigned short year, month, day;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Date().DecodeDate( &year, &month, &day);
    Valeur = day;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::CurrentMonth( bool bAFaire)
{
    unsigned short year, month, day;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Date().DecodeDate( &year, &month, &day);
    Valeur = month;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::CurrentYear( bool bAFaire)
{
    unsigned short year, month, day;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Date().DecodeDate( &year, &month, &day);
    Valeur = year;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::CurrentHour( bool bAFaire)
{
    unsigned short hour, min, sec, msec;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Time().DecodeTime( &hour, &min, &sec, &msec);
    Valeur = hour;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::CurrentMin( bool bAFaire)
{
    unsigned short hour, min, sec, msec;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Time().DecodeTime( &hour, &min, &sec, &msec);
    Valeur = min;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::CurrentSec( bool bAFaire)
{
    unsigned short hour, min, sec, msec;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Time().DecodeTime( &hour, &min, &sec, &msec);
    Valeur = sec;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarNum::IsNull( bool bAFaire)
{
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( Valeur, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ")"));
    return IsDNS(Valeur)?"1":"0";
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
void __fastcall TVarChaine :: Help( TTreeNode *t)
{
  m_Calc->Help(t,TabHelp,ARRAYSIZE(TabHelp));
}
/*void  __fastcall  TVarChaine:: Help( TTreeNode *tNode)
{
    m_Calc->AddHelp( tNode, "+",                    "<Variable string> += <expression string>");
    m_Calc->AddHelp( tNode, "+=",                   "<expression string> += <expression string>");
    m_Calc->AddHelp( tNode, "LowerCase",            "LowerCase( string s)");
    m_Calc->AddHelp( tNode, "UpperCase",            "UpperCase( string s)");
    m_Calc->AddHelp( tNode, "NumToString",          "NumToString( num x)");
    m_Calc->AddHelp( tNode, "CurrentDateToStr",     "CurrentDateToStr( )");
    m_Calc->AddHelp( tNode, "CurrentTimeToStr",     "CurrentTimeToStr( )");
    m_Calc->AddHelp( tNode, "CurrentDateTimeToStr", "CurrentDateTimeToStr( )");
    m_Calc->AddHelp( tNode, "SubString",            "SubString( string s, num index, num count)");
}*/
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::operator>=( bool bAFaire)
{
    AnsiString a;
    TVarChaine *v = new TVarChaine( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
    delete v;
    return Valeur >= a? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::operator<=( bool bAFaire)
{
    AnsiString a;
    TVarChaine *v = new TVarChaine( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
    delete v;
    return Valeur <= a? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::operator>( bool bAFaire)
{
    AnsiString a;
    TVarChaine *v = new TVarChaine( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
    delete v;
    return Valeur > a? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::operator<( bool bAFaire)
{
    AnsiString a;
    TVarChaine *v = new TVarChaine( m_Calc, "Temporaire");
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, v));
    delete v;
    return Valeur < a? "1":"0";
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::operator+( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL, EL_Simple));
    return AnsiString( Valeur + a);
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::operator+=( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    Valeur += a;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::LowerCase( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Valeur = a.LowerCase();
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::UpperCase( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Valeur = a.UpperCase();
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::NumToString( bool bAFaire)
{
    AnsiString a;
    TVarNum *pv = new TVarNum( m_Calc, "Temporaire");;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, pv));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Valeur = a;
    delete pv;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::SubString( bool bAFaire)
{
    AnsiString a, ab, ac;
    TVarNum *pv = new TVarNum( m_Calc, "Temporaire");

    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ","));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( ab, bAFaire, pv));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant( ","));
    pv->Valeur = 0;
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( ac, bAFaire, pv));

    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Valeur = a.SubString( ab.ToInt(), ac.ToInt());
    delete pv;
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::CurrentDateToStr( bool bAFaire)
{
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Valeur = Date().DateString();
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::CurrentTimeToStr( bool bAFaire)
{
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Valeur = Time().TimeString();
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::CurrentDateTimeToStr( bool bAFaire)
{
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Valeur = TDateTime::CurrentDateTime().DateTimeString();
    return Valeur;
}
//---------------------------------------------------------------------------
AnsiString __fastcall TVarChaine::Trim( bool bAFaire)
{
    AnsiString a;
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant("("));
    m_Calc->throwIfFalse( m_Calc->LireGroupeElement( a, bAFaire, NULL));
    m_Calc->throwIfFalse( m_Calc->LitMotSuivant(")"));
    Valeur = a.Trim();
    return Valeur;
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
__fastcall TCalculDeFormules :: TCalculDeFormules( const AnsiString &Texte):TComponent(NULL)
{
    m_LstVar = new TStringList();
    m_Formule = Texte;
    Init( );
}
//---------------------------------------------------------------------------
__fastcall TCalculDeFormules :: ~TCalculDeFormules()
{
    Init( );
    delete m_LstVar;
}
//---------------------------------------------------------------------------
void __fastcall TCalculDeFormules :: Init( )
{
    m_nIndice = 1;
    m_nLigne = 1;
    m_nValRetour = 0;
    m_bPremierReturn = true;
    while( m_LstVar->Count)
    {
        delete (TVar*)m_LstVar->Objects[ 0];
        m_LstVar->Delete( 0);
    }
    m_Resultat = EmptyStr;
}

//---------------------------------------------------------------------------
void __fastcall TCalculDeFormules :: SetFormule( const AnsiString &Formule)
{
    if( m_bCalcEncours) return;
    m_Formule = EmptyStr;
    for( int i=1; i <= Formule.Length(); i++)
    {
        if( Formule[i] == '\\' && i < Formule.Length() )
        {
            i++;
            switch(Formule[i])
            {
                case 'r' : m_Formule += '\r'; break;
                case 'n' : m_Formule += '\n'; break;
                case 't' : m_Formule += '\t'; break;
                case '\\': m_Formule += '\\'; break;
                case '0' : m_Formule += '\0'; break;
            }
        }else m_Formule += Formule[i];
    }
}

//---------------------------------------------------------------------------
void __fastcall TCalculDeFormules :: Message( const AnsiString &aMessage )
{
    if( m_OnError)
       m_OnError( aMessage);
}
//---------------------------------------------------------------------------
void __fastcall TCalculDeFormules :: throwIfFalse( bool b, const AnsiString &s)
{
    if( !b)
    {
        Erreur(s);
        throw Exception(s);
    }
}
void __fastcall TCalculDeFormules :: Erreur( const AnsiString &aMessage )
{
    if( m_OnError)
       m_OnError( "Erreur ligne "+AnsiString(m_nLigne)+" : "+aMessage);
}
//---------------------------------------------------------------------------
void __fastcall TCalculDeFormules :: Avertissement( const AnsiString &aMessage )
{
    if( m_OnError)
       m_OnError( "Warning ligne "+AnsiString(m_nLigne)+" : "+aMessage);
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: bIsLettre( char Car )
{
    return (  (  (Car >= 'a')
               &&(Car <= 'z'))
            ||(  (Car >= 'A')
               &&(Car <= 'Z'))
            ||   (Car == '_') );
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: bIsChiffre( char Car )
{
    return ((  (Car >= '0')
             &&(Car <= '9'))
            || (Car == '.'));
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: bIsBlanc( char Car )
{
    return (  (Car == ' ')
            ||(Car == '\t')
            ||(Car == '\r')
            ||(Car == '\n'));
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: bIsProg( char Car )
{
    return (  (Car == ';')
            ||(Car == ',')
            ||(Car == '(')
            ||(Car == ')')
            ||(Car == '{')
            ||(Car == '}'));
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: bIsOperateur( char Car )
{
    return (  (Car == '=')
            ||(Car == '<')
            ||(Car == '+')
            ||(Car == '-')
            ||(Car == '*')
            ||(Car == '/')
            ||(Car == '&')
            ||(Car == '|')
            ||(Car == '!')
            ||(Car == '>'));
}

//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: bIsSautLigne( char Car )
{
    return (Car == '\n');
}

//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: bIsGuillemet( char Car )
{
    return (Car == '\"');  // -> ' " '
}

//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: bIsCaractere (char Car )
{
    if ( (Car >= (char)0x20) || ((Car <= 0) && (Car >= (char)0xA0)) )return true;
    else return false;
}
//---------------------------------------------------------------------------
bool  __fastcall TCalculDeFormules :: IsNomOperateur( const AnsiString &s)
{
    if( !s.Length()) return false;
    for( int i=1; i <= s.Length(); i++)
    {
        if( !bIsOperateur( s[i])) return false;
    }
    return true;
}
//---------------------------------------------------------------------------
bool  __fastcall TCalculDeFormules :: IsNomVar (const AnsiString &s)
{
    if( !s.Length()) return false;
    for( int i=1; i <= s.Length(); i++)
    {
        if( (i==1)? !bIsLettre( s[i]) : !bIsLettre( s[i]) && !bIsChiffre( s[i])) return false;
    }
    return true;
}
//---------------------------------------------------------------------------
bool  __fastcall TCalculDeFormules :: IsString( const AnsiString &s)
{
    if( !s.Length()) return false;
    for( int i=1; i <= s.Length(); i++)
    {
        if( !bIsCaractere( s[i])) return false;
    }
    return true;
}
//---------------------------------------------------------------------------
bool  __fastcall TCalculDeFormules :: IsNombre (const AnsiString &s)
{
    AnsiString s2 = s;
    if( !s2.Length()) return false;
    for( int i = 1; i <= s2.Length(); i++)
    {
        if( !bIsChiffre( s2[i])) return false;
        if( s2[i] == '.') s2[i] = DecimalSeparator;
    }
    try{
        s2.ToDouble();
    }catch( EConvertError &e)
    {
        return false;
    }
    return true;
}
//---------------------------------------------------------------------------
void __fastcall TCalculDeFormules :: PasseBlancs()
{
    if (m_nIndice > m_Formule.Length()) return;
    while(bIsBlanc(m_Formule[m_nIndice])) {
        m_nIndice++;
        if (m_nIndice > m_Formule.Length()) return;
        if (bIsSautLigne(m_Formule[m_nIndice]))  m_nLigne++;
    }
}
//---------------------------------------------------------------------------
TYPE_CAR __fastcall TCalculDeFormules :: nTypeCar( char Car )
{
//Si Car est une lettre,
    if (bIsLettre( Car ))       return TC_LETTRE;
//Si Car est un espace,
    if (bIsBlanc( Car ))        return TC_BLANC;
//Si Car est un chiffre,
    if (bIsChiffre( Car ))      return TC_CHIFFRE;
//Si Car est un opérateur = < >,
    if (bIsOperateur( Car ))    return TC_OPERATEUR;
//Si Car est un ; ( ) { }
    if (bIsProg( Car ))         return TC_PROG;
//Si Car est un guillemet
    if (bIsGuillemet( Car ))    return TC_GUIL;
//Sinon
    return TC_NOTYPE;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: DonneMotSuivant( AnsiString &aMot )
{
    int nIndiceInter ; //= m_nIndice; // il ne faut pas avancer dans le mot (il n'est pas réèlement lu)
    aMot = EmptyStr;
//passe au mot suivant
    PasseBlancs();
    nIndiceInter = m_nIndice;
    if (nIndiceInter > m_Formule.Length()) return false;
    TYPE_CAR TypeC;
    TypeC = nTypeCar(m_Formule[nIndiceInter]);
    while(  (nIndiceInter <= m_Formule.Length())
//          &&(TypeC != TC_PROG)
          &&((TypeC == nTypeCar(m_Formule[nIndiceInter])) || ((TypeC == TC_LETTRE) && (nTypeCar(m_Formule[nIndiceInter]) == TC_CHIFFRE)))) {
        aMot += AnsiString(m_Formule[nIndiceInter]);
        nIndiceInter++;
        if( TypeC == TC_PROG) break;
    }
//renvoie true si chaine non vide
    return !aMot.IsEmpty();
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: LitMotSuivant( const AnsiString &aChaine )
{
    char cInter;
    PasseBlancs();
    if (m_nIndice > m_Formule.Length()) return false;
    for( int i=0; (i < aChaine.Length()) && (m_nIndice+i <= m_Formule.Length()); i++) {
        cInter = m_Formule[m_nIndice+i];
        if (aChaine[i+1] != cInter) return false;
    }
    m_nIndice += aChaine.Length();
    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: LireJusqu_a( AnsiString &aChaine, char c)
{
    bool bIsGuillemet = false;
    aChaine = EmptyStr;
    for( ; bIsGuillemet? true :m_Formule[m_nIndice] != c; m_nIndice++) {
        if( m_Formule[m_nIndice] == '\"')
            bIsGuillemet = !bIsGuillemet;
        aChaine += m_Formule[m_nIndice];
        if (m_nIndice > m_Formule.Length())
            throw Exception( "Fin de bloc '" + AnsiString(c) +"' non trouvé");
    }
    return true;
}
//---------------------------------------------------------------------------
TVar* __fastcall TCalculDeFormules :: GetVariable( const AnsiString &aChaine)
{
    if( m_LstVar->IndexOf( aChaine ) != -1)
    {
        return (TVar *)m_LstVar->Objects[m_LstVar->IndexOf( aChaine )];
    }
    else if( m_OnVariableEvent)
    {
        TFieldType Type;
        AnsiString Valeur;
        if( m_OnVariableEvent( aChaine, Type, Valeur))
        {
            TVar* v;
            if( Type == ftFloat) v = new TVarNum(this, aChaine);
            else                 v = new TVarChaine(this, aChaine);
            v->Valeur = Valeur;
            m_LstVar->AddObject( aChaine, (TObject*)v);
            return v;
        }
    }
    return NULL;
}
//---------------------------------------------------------------------------
bool      __fastcall TCalculDeFormules :: LitNomVariable( AnsiString &s )
{
    if( DonneMotSuivant( s) && IsNomVar( s))
        return LitMotSuivant( s);
    return false;
}

//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: LireCondition( bool &bValeur, bool bAFaire )
{
    AnsiString aValeur;
    if( !LireGroupeElement( aValeur, true)) {Erreur( "Condition non valide"); return false;}
    bValeur = !aValeur.IsEmpty() && aValeur != "0";
    return true;
}


bool __fastcall TCalculDeFormules :: LireElement( AnsiString &aRetour, TFieldType &Type, bool bAFaire,
                                                  TVar *pvEntree, TYPE_EL bComplexe)
{
    TVarNum    *vn = dynamic_cast<TVarNum *>(pvEntree);
    TVarChaine *vc = dynamic_cast<TVarChaine *>(pvEntree);
    AnsiString aVariable;
    bool vRetour = false, bDelv = false;
    Type = ftUnknown;

    aRetour = EmptyStr;
    DonneMotSuivant( aVariable);
    if( aVariable == ';') return false;
    if( IsNomVar( aVariable) || IsNomOperateur( aVariable))
    {
        TVar *v= NULL;
        VAR_FUNC Fnc = 0;
        if( !pvEntree || vn)
        {      /* Fonction numérique autorisée ? */
            if( vn) v = vn;
            else{   v = new TVarNum( this, "Temporaire");    bDelv = true; }
            Fnc = (VAR_FUNC)SetFonction( v, aVariable);
        }
        if( !Fnc && (!pvEntree || vc))
        {  /* Fonction chaine autorisée ? */
            if( bDelv) delete v;
            if( vc) v = vc;
            else{   v = new TVarChaine( this, "Temporaire"); bDelv = true; }
            Fnc = (VAR_FUNC)SetFonction( v, aVariable);
        }

        if( Fnc)
        {   /* on est en présence  d'une fonction */
            AnsiString aInter;
            LitMotSuivant( aVariable);
            aInter = Fnc( bAFaire);
            if( bAFaire)   aRetour = aInter;
            Type = v->Type;
            vRetour = true;
        }
        if( bDelv) { delete v; v = NULL; bDelv = false;}
                      
        if( !vRetour && IsNomVar( aVariable)){
            v = GetVariable( aVariable);
            if( v){ /* c'est une variable */
                LitMotSuivant( aVariable);
                if( (!bComplexe || !LireGroupeElement( aRetour, bAFaire, v)) && bAFaire)
                    aRetour = v->Valeur;
                Type = v->Type;
                vRetour = true;
            }else{
                throwIfFalse(false, "Mot non reconnu '"+aVariable+"'");
            }
        }
    }else if( IsNombre( aVariable)) {
        LitMotSuivant( aVariable);
        int n = aVariable.Pos(".");
        if( n) aVariable[n] = DecimalSeparator;
        if( bAFaire) aRetour = aVariable;
        Type = ftFloat;
        vRetour = true;
    }else if( aVariable == "\"") {
        LitMotSuivant( aVariable);
        LireJusqu_a(aVariable, '\"');
        LitMotSuivant( '\"');
        if( bAFaire) aRetour = aVariable;
        Type = ftString;
        vRetour = true;
    }else if( aVariable == "\"\"") {
        LitMotSuivant( aVariable);
        aVariable = EmptyStr;
        if( bAFaire) aRetour = aVariable;
        Type = ftString;
        vRetour = true;
    }
    return vRetour;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: LireGroupeElement( AnsiString &aRetour, bool bAFaire,
                                                        TVar *pv, TYPE_EL bComplexe)
{
    AnsiString aVariable;
    bool parenthese, bRelitElement;
    bool vRetour = false;
    TFieldType Type;

    aRetour = EmptyStr;
    parenthese = LitMotSuivant ("(");

    vRetour = LireElement( aRetour, Type, bAFaire, parenthese?NULL:pv, bComplexe);
    if( !vRetour) return false;
  #ifdef _DEBUG
    if( !parenthese)
        ASSERT( (!pv && ((Type == ftFloat) || (Type == ftString)))
                || (pv->Type == Type));
  #endif

    if( parenthese || bComplexe)
        do{
            if ( DonneMotSuivant( aVariable) &&
                    ( !bIsProg( aVariable[1]) ||
                      (aVariable[1] == '(')  ) )
            {
                TVar *v = (Type==ftFloat)? (TVar*)new TVarNum( this, "Temp")
                                         : (TVar*)new TVarChaine( this, "Temp");
                v->Valeur = aRetour;
                vRetour = LireGroupeElement( aRetour, bAFaire, v, bComplexe);
                delete v;
            }

            if( parenthese )
            {
                vRetour = LitMotSuivant(")");
                parenthese = false;
                /* On peut avoir un autre élément derrière la parenthèse */
                bRelitElement =true;
    //            if( bDelv) { delete v; bDelv = false; }
    //            v = NULL;
            }else bRelitElement = false;
        }while( bRelitElement);
    return vRetour;
}

//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: _return( bool bAFaire)
{
    AnsiString aChaine;
        /* return <Element>; */
    LireGroupeElement( aChaine, bAFaire);
    if (!LitMotSuivant(";"))              { Erreur("Toute instruction doit se terminer par ';'"); return false; }
    if ( bAFaire) {
        m_Resultat = aChaine;
        throw EAbort("return");
    }
    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: _if( bool bAFaire)
{
    AnsiString aMotSuivant;
        /* if (<Condition>) <GroupeInstructionsSimple> {else <GroupeInstructionsSimple>}*/
    bool bValeur;
    if (!LitMotSuivant("("))                { Erreur("Syntaxe : if (Cond) {Trait} : '(' attendu"); return false; }
    if (!LireCondition( bValeur, bAFaire))  { Erreur("Condition attendue après le 'if'"); return false; }
    if (!LitMotSuivant(")"))                { Erreur("Syntaxe : if (Cond) {Trait} : ')' attendu"); return false; }
    if (!LireGroupeInstructionsSimple( bValeur))  return false;
    if ( DonneMotSuivant( aMotSuivant ) && (aMotSuivant == "else")) {
        if (!LitMotSuivant("else"))             { Erreur("Erreur interne : imossible de relire 'else'"); return false; }
        if (!LireGroupeInstructionsSimple(!bValeur)) return false;
    }
    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: _for( bool bAFaire)
{
        /* for( <Instruction>; <Condition>; <Instruction>;) <GroupeInstructionsSimple> */
    bool bValeur;
    int nIndiceCond, nIndiceInstruction, nIndiceGpInstruction;
    if (!LitMotSuivant("("))                { Erreur("Syntaxe : for( Init; Cond; Trait ) { Trait } ) : '(' attendu"); return false; }
    if (!LireInstruction(false))  return false;
    nIndiceCond = m_nIndice;
    if (!LireCondition( bValeur, bAFaire))  { Erreur("Condition attendue"); return false; }
    if (!LitMotSuivant(";"))                { Erreur("Syntaxe : for( Init; Cond; Trait ) { Trait } )"); return false; }
    nIndiceInstruction = m_nIndice;
    if (!LireInstruction(false)) return false;
    if (!LitMotSuivant(")"))                { Erreur("Syntaxe : for( Init; Cond; Trait ) { Trait } )"); return false; }
    nIndiceGpInstruction = m_nIndice;

    do
    {
        m_nIndice = nIndiceCond;
        if( !LireCondition( bValeur, bAFaire))     { Erreur("Condition attendue"); return false; }

        m_nIndice = nIndiceGpInstruction;
        if( !LireGroupeInstructionsSimple( bAFaire && bValeur))   return false;

        if( bValeur)
        {
            m_nIndice = nIndiceInstruction;
            if( !LireInstruction( bAFaire))   return false;
        }
    }while( bValeur );
    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: _do( bool bAFaire)
{
        /* do { <GroupeInstructions> } while (<Condition>)  */
    bool bValeur;
    int nIndiceDebut;
    nIndiceDebut = m_nIndice;
    bValeur = true;
    while (bValeur)
    {
        m_nIndice = nIndiceDebut;
        if (!LitMotSuivant("{"))                { Erreur("Syntaxe : do {Trait} while (Cond); : '{' attendu "); return false; }
        if (!LireGroupeInstructionsComplexe( bValeur)) return false;
        if (!LitMotSuivant("}"))                { Erreur("Syntaxe : do {Trait} while (Cond); : '}' attendu "); return false; }
        if (!LitMotSuivant("while"))            { Erreur("Syntaxe : do {Trait} while (Cond); : 'while' attendu"); return false; }
        if (!LitMotSuivant("("))                { Erreur("Syntaxe : do {Trait} while (Cond); : '(' attendu "); return false; }
        if (!LireCondition( bValeur, bAFaire))  { Erreur("Condition attendue"); return false; }
        if (!LitMotSuivant(")"))                { Erreur("Syntaxe : do {Trait} while (Cond); : ')' attendu "); return false; }
        if (!LitMotSuivant(";"))                { Erreur("Syntaxe : do {Trait} while (Cond); attendu ;"); return false; }
    }
    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: _while( bool bAFaire)
{
        /* while (<Condition>) <GroupeInstructionsSimple> */
    bool bValeur;
    int nIndiceDebut;
    if (!LitMotSuivant("("))                { Erreur("Syntaxe : while (Cond} {Trait) : '(' attendu "); return false; }
    nIndiceDebut = m_nIndice;
    bValeur = true;
    while (bValeur)
    {
        m_nIndice = nIndiceDebut;
        if (!LireCondition( bValeur, bAFaire))  { Erreur("Condition attendue"); return false; }
        if (!LitMotSuivant(")"))                { Erreur("Syntaxe : while (Cond} {Trait) : ')' attendu "); return false; }
        if (!LireGroupeInstructionsSimple( bValeur)) return false;
    }
    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: _num( bool bAFaire)
{
    AnsiString aVariable;
    if( LitNomVariable( aVariable))
    {
        if( m_LstVar->IndexOf( aVariable ) != -1)  {Erreur("Erreur interne : déja defini"); return false; }

        TVarNum *Res = new TVarNum(this, aVariable);
        m_LstVar->AddObject( aVariable, (TObject *)Res );

        LireGroupeElement( aVariable, bAFaire, Res);
        if ( LitMotSuivant(","))  _num( bAFaire);
        else
            if (!LitMotSuivant(";"))             { Erreur("Toute instruction doit se terminer par ';'"); return false; }
    }
    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: _string( bool bAFaire)
{
    AnsiString aVariable;
    if( LitNomVariable( aVariable))
    {
        if( m_LstVar->IndexOf( aVariable ) != -1)  { Erreur("Erreur interne : déja defini"); return false; }

        TVarChaine *Res = new TVarChaine(this, aVariable);
        m_LstVar->AddObject( aVariable, (TObject *)Res );

        LireGroupeElement( aVariable, bAFaire, Res);
        if ( LitMotSuivant(","))  _string( bAFaire);
        if (!LitMotSuivant(";"))                 { Erreur("Toute instruction doit se terminer par ';'"); return false; }
    }
    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: LireInstruction( bool bAFaire )
{
    AnsiString aMotSuivant, aChaine;
    DonneMotSuivant( aMotSuivant );
    if (aMotSuivant == ";") {
        if (!LitMotSuivant(";")) { Erreur("Erreur interne : impossible de relire le mot ';'"); return false; }
    }else
    {
        VAR_INSTR Instr = 0;
        Instr = (VAR_INSTR)SetFonction( this, "_" + aMotSuivant);
        if( Instr)
        {
            AnsiString aInter;
            if (!LitMotSuivant(aMotSuivant)) { Erreur("Erreur interne : impossible de relire le mot '"+aMotSuivant+"'"); return false; }

            Instr( bAFaire);
        }else {//if( LitNomVariable( aMotSuivant)){
//            TVar *v = GetVariable( aMotSuivant);
            /*if( !v) { Erreur("Mot non reconnu '"+ aMotSuivant +"'"); return false; }
            else */LireGroupeElement( aMotSuivant, bAFaire, NULL);
            LitMotSuivant(";");
        }
    }
    return true;
}
//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: LireGroupeInstructions( bool bAFaire, bool bUnique )
{
    AnsiString aMotSuivant;
    PasseBlancs();
    if( DonneMotSuivant( aMotSuivant )){
        if( aMotSuivant == "}");
        else if( aMotSuivant == "{")
        {
            LitMotSuivant( aMotSuivant);
            if( bAFaire)
            {
                if (!LireGroupeInstructionsComplexe( bAFaire))
                    return false;
            }else
                LireJusqu_a( aMotSuivant, '}');
            if( !LitMotSuivant("}"))  { Erreur("'}' attendu après le groupe d'instructions"); return false; }
        }
        else
        {
            if( bAFaire)
            {
                if( !LireInstruction( bAFaire ))
                    return false;
            }else{
                LireJusqu_a( aMotSuivant, ';');
                LitMotSuivant(";");
            }
            if( !bUnique)
                if (!LireGroupeInstructionsComplexe( bAFaire)) return false;
        }
    }
    return true;
}

//---------------------------------------------------------------------------
bool __fastcall TCalculDeFormules :: Execute( AnsiString &Resultat)
{
    bool bOk;
    if( m_bCalcEncours) return false;
    m_bCalcEncours = true;
    Resultat = EmptyStr;
    try{
        Init( );
        bOk = LireGroupeInstructionsComplexe( true );
        if( bOk) Resultat = m_Resultat;
    }catch( EAbort &e){
        bOk = true;
        Resultat = m_Resultat;
    }
    catch( ...)
    {
        bOk = false;
    }
    m_bCalcEncours = false;
    return bOk;
}

void  __fastcall TCalculDeFormules :: AddHelp( TTreeNode *tNode, const AnsiString &MotCle, const char* pComment)
{
    ((TTreeView*)tNode->TreeView)->Items->AddChildObject( tNode, MotCle, (void*)pComment);
}

void __fastcall TCalculDeFormules::Help( TTreeNode *t,const cHelp *Tableau,int Taille)
{
  for (int i = 0;i < Taille;i++)
    AddHelp(t,Tableau[i].Nom,Tableau[i].Prototype);
}
void __fastcall TCalculDeFormules :: Help( TTreeNode *t)
{
  Help(t,TabHelp,ARRAYSIZE(TabHelp));
}
/*void  __fastcall  TCalculDeFormules :: Help( TTreeNode *tNode)
{
    AddHelp( tNode, "return", "return [ <expression>] ;");
    AddHelp( tNode, "if", "if( <condition>)  <instruction1>;\nelse  <instruction2>;");
    AddHelp( tNode, "else", "if( <condition>)  <instruction1>;\nelse  <instruction2>;");
    AddHelp( tNode, "for", "for ( [<initialisation>]; [<condition>]; [<incrément>] )  <instruction>");
    AddHelp( tNode, "do", "do <instruction> while( <condition> );");
    AddHelp( tNode, "while", "while( <condition>) <instruction>");
    AddHelp( tNode, "num", "Déclaration de variable numérique");
    AddHelp( tNode, "string", "Déclaration de variable alphanumérique");
}*/

void  __fastcall  TCalculDeFormules :: FonctionsDispo( TTreeNodes *li)
{
    TTreeNode *second;
    TVar *v; TVarNum *vn; TVarChaine *vc;
    second = li->Add( li->GetFirstNode(), "Instructions");
        Help( second);

    v = new TVar( this, "Temp");
    second = li->Add( li->GetFirstNode(), "Fonctions numériques et alphanumériques");
        v->Help( second);
    delete v;

    vn = new TVarNum( this, "Temp");
    second = li->Add( li->GetFirstNode(), "Fonctions numériques");
        vn->Help( second);
    delete vn;

    vc = new TVarChaine( this, "Temp");
    second = li->Add( li->GetFirstNode(), "Fonctions alphanumériques");
        vc->Help( second);
    delete vc;
}



void ETATAPI GetMotsCles( TTreeNodes *li)
{
    TCalculDeFormules *c = new TCalculDeFormules( );
    c->FonctionsDispo( li);
    delete c;
}
